﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Data;


public class ADHelper
{
    #region 私有变量
    /// <summary>
    /// homeMTA
    /// </summary>
    private string homeMTA = ""; //请填写自己的环境变量
    /// <summary>
    /// homeMDB
    /// </summary>
    private string homeMDB = ""; //请填写自己的环境变量
    /// <summary>
    /// msExchHomeServerName
    /// </summary>
    private string msExchHomeServerName = ""; //请填写自己的环境变量

    /// <summary>
    /// 域名
    /// </summary>
    private string DomainName = "BMCServer";
    /// <summary>
    /// LDAP 地址
    /// </summary>
    private string LDAPDomain = "DC=BMCServer,DC=com";
    /// <summary>
    /// LDAP绑定路径
    /// </summary>
    private string ADPath = "LDAP://BMCServer.com";
    private string sPrincpleNameTail = "@cinf.com";
    /// <summary>
    /// 登录帐号
    /// </summary>
    private string ADUser = "Manager";
    /// <summary>
    /// 登录密码
    /// </summary>
    private string ADPassword = "Pass@word";
    //private  string ADPassword = "";

    #endregion

    #region 枚举常量
    /// <summary>
    /// 用户登录验证结果
    /// </summary>
    public enum LoginResult
    {
        ///
        /// 正常登录
        ///
        LOGIN_USER_OK = 0,
        ///
        /// 用户不存在
        ///
        LOGIN_USER_DOESNT_EXIST,
        ///
        /// 用户帐号被禁用
        ///
        LOGIN_USER_ACCOUNT_INACTIVE,
        ///
        /// 用户密码不正确
        ///
        LOGIN_USER_PASSWORD_INCORRECT
    }
    /// <summary>
    /// 用户属性定义标志
    /// </summary>
    public enum ADS_USER_FLAG_ENUM
    {
        ///
        /// 登录脚本标志。如果通过 ADSI LDAP 进行读或写操作时，
        /// 该标志失效。如果通过 ADSI WINNT，该标志为只读。
        ///
        ADS_UF_SCRIPT = 0X0001,
        ///
        /// 用户帐号禁用标志
        ///
        ADS_UF_ACCOUNTDISABLE = 0X0002,
        ///
        /// 主文件夹标志
        ///
        ADS_UF_HOMEDIR_REQUIRED = 0X0008,
        ///
        /// 过期标志
        ///
        ADS_UF_LOCKOUT = 0X0010,
        ///
        /// 用户密码不是必须的
        ///
        ADS_UF_PASSWD_NOTREQD = 0X0020,
        ///
        /// 密码不能更改标志
        ///
        ADS_UF_PASSWD_CANT_CHANGE = 0X0040,
        ///
        /// 使用可逆的加密保存密码
        ///
        ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0X0080,
        ///
        /// 本地帐号标志
        ///
        ADS_UF_TEMP_DUPLICATE_ACCOUNT = 0X0100,
        ///
        /// 普通用户的默认帐号类型
        ///
        ADS_UF_NORMAL_ACCOUNT = 0X0200,
        ///
        /// 跨域的信任帐号标志
        ///
        ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 0X0800,
        ///
        /// 工作站信任帐号标志
        ///
        ADS_UF_WORKSTATION_TRUST_ACCOUNT = 0x1000,
        ///
        /// 服务器信任帐号标志
        ///
        ADS_UF_SERVER_TRUST_ACCOUNT = 0X2000,
        ///
        /// 密码永不过期标志
        ///
        ADS_UF_DONT_EXPIRE_PASSWD = 0X10000,
        ///
        /// MNS 帐号标志
        ///
        ADS_UF_MNS_LOGON_ACCOUNT = 0X20000,
        ///
        /// 交互式登录必须使用智能卡
        ///
        ADS_UF_SMARTCARD_REQUIRED = 0X40000,
        ///
        /// 当设置该标志时，服务帐号（用户或计算机帐号）将通过 Kerberos 委托信任
        ///
        ADS_UF_TRUSTED_FOR_DELEGATION = 0X80000,
        ///
        /// 当设置该标志时，即使服务帐号是通过 Kerberos 委托信任的，敏感帐号不能被委托
        ///
        ADS_UF_NOT_DELEGATED = 0X100000,
        ///
        /// 此帐号需要 DES 加密类型
        ///
        ADS_UF_USE_DES_KEY_ONLY = 0X200000,
        ///
        /// 不要进行 Kerberos 预身份验证
        ///
        ADS_UF_DONT_REQUIRE_PREAUTH = 0X4000000,
        ///
        /// 用户密码过期标志
        ///
        ADS_UF_PASSWORD_EXPIRED = 0X800000,
        ///
        /// 用户帐号可委托标志
        ///
        ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0X1000000

    }
    #endregion

    #region 构造函数
    public ADHelper()
    {
        ADPath = "LDAP://founder";
        DomainName = "founder";
        ADUser = "zyadmin";
        ADPassword = "Founder@2012";
    }

    /// <summary>
    /// 多联的AD构造函数
    /// </summary>
    /// <param name="sADPath"></param>
    /// <param name="sDomainName"></param>
    /// <param name="sADUser"></param>
    /// <param name="sADUserPWD"></param>
    public ADHelper(string sADPath, string sDomainName, string sADUser, string sADUserPWD)
    {
        ADPath = sADPath;
        DomainName = sDomainName;
        ADUser = sADUser;
        ADPassword = sADUserPWD;
    }
    #endregion

    #region GetDirectoryObject

    /// <summary>
    /// 获得DirectoryEntry对象实例,以管理员登陆AD
    /// </summary>
    /// <returns></returns>
    private DirectoryEntry GetDirectoryObject()
    {
        DirectoryEntry entry = new DirectoryEntry(ADPath, ADUser, ADPassword, AuthenticationTypes.Secure);
        return entry;
    }

    /// <summary>
    /// 根据指定用户名和密码获得相应DirectoryEntry实体
    /// </summary>
    /// <param name="userName"></param>
    /// <param name="password"></param>
    /// <returns></returns>
    private DirectoryEntry GetDirectoryObject(string userName, string password)
    {
        DirectoryEntry entry = new DirectoryEntry(ADPath,
            userName, password, AuthenticationTypes.None);
        return entry;
    }

    /// <summary>
    /// i.e. /CN=Users,DC=creditsights, DC=cyberelves, DC=Com
    /// </summary>
    /// <param name="domainReference"></param>
    /// <returns></returns>
    private DirectoryEntry GetDirectoryObject(string domainReference)
    {
        DirectoryEntry entry = new DirectoryEntry(ADPath + domainReference, ADUser, ADPassword,
            AuthenticationTypes.Secure);
        return entry;
    }

    /// <summary>
    ///  获得以UserName,Password创建的DirectoryEntry
    /// </summary>
    /// <param name="domainReference"></param>
    /// <param name="userName"></param>
    /// <param name="password"></param>
    /// <returns></returns>
    private DirectoryEntry GetDirectoryObject(string domainReference,
        string userName, string password)
    {
        DirectoryEntry entry = new DirectoryEntry(ADPath + domainReference,
            userName, password, AuthenticationTypes.Secure);
        return entry;
    }

    #endregion

    #region GetDirectoryEntry



    /// <summary>
    /// 根据用户公共名称取得用户的 对象
    /// </summary>
    /// <param name="commonName">用户公共名称</param>
    /// <returns>如果找到该用户，则返回用户的 对象；否则返回 null</returns>
    public DirectoryEntry GetDirectoryEntry(string commonName)
    {
        DirectoryEntry de = GetDirectoryObject();
        DirectorySearcher deSearch = new DirectorySearcher(de);
        deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(cn=" +
commonName + "))";
        deSearch.SearchScope = SearchScope.Subtree;
        try
        {
            SearchResult result = deSearch.FindOne();
            de = new DirectoryEntry(result.Path);
            //de.Username = ADUser;
            return de;
        }
        catch
        {
            return null;
        }
    }



    /// <summary>
    /// 根据用户公共名称和密码取得用户的 对象。
    /// </summary>
    /// <param name="commonName">用户公共名称</param>
    /// <param name="password">用户密码</param>
    /// <returns>如果找到该用户，则返回用户的 对象；否则返回 null</returns>
    public DirectoryEntry GetDirectoryEntry(string commonName, string password)
    {
        DirectoryEntry de = GetDirectoryObject(commonName, password);
        DirectorySearcher deSearch = new DirectorySearcher(de);
        deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(cn=" + commonName + "))";
        deSearch.SearchScope = SearchScope.Subtree;
        try
        {
            SearchResult result = deSearch.FindOne();
            de = new DirectoryEntry(result.Path);
            return de;
        }
        catch
        {
            return null;
        }
    }



    /// <summary>
    /// 根据用户帐号称取得用户的 对象
    /// </summary>
    /// <param name="sAMAccountName">用户帐号名</param>
    /// <returns>如果找到该用户，则返回用户的 对象；否则返回 null</returns>
    public DirectoryEntry GetDirectoryEntryByAccount(string sAMAccountName)
    {
        DirectoryEntry user = null;
        DirectoryEntry de = GetDirectoryObject(ADUser, ADPassword);
        DirectorySearcher deSearch = new DirectorySearcher(de);
        deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(sAMAccountName=" + sAMAccountName + "))";
        deSearch.SearchScope = SearchScope.Subtree;
        try
        {
            SearchResult result = deSearch.FindOne();
            if (result != null)
            {
                user = new DirectoryEntry(result.Path, ADUser, ADPassword);
            }

        }
        catch
        {

        }
        finally
        {
            deSearch.Dispose();
        }
        return user;
    }

    public List<DirectoryEntry> GetListByAccount(string sAMAccountName)
    {
        List<DirectoryEntry> userList = new List<DirectoryEntry>();

        DirectoryEntry de = GetDirectoryObject(ADUser, ADPassword);
        DirectorySearcher deSearch = new DirectorySearcher(de);
        deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(sAMAccountName=" + sAMAccountName + "*))";
        deSearch.SearchScope = SearchScope.Subtree;

        try
        {
            SearchResultCollection result = deSearch.FindAll();
            if (result != null)
            {
                foreach (SearchResult item in result)
                {
                    DirectoryEntry user = new DirectoryEntry(item.Path, ADUser, ADPassword);
                    userList.Add(user);
                }
            }

        }
        catch
        {

        }
        deSearch.Dispose();

        return userList;
    }

    /// <summary>
    /// 根据用户帐号和密码取得用户的 对象
    /// </summary>
    /// <param name="sAMAccountName">用户帐号名</param>
    /// <param name="password">用户密码</param>
    /// <returns>如果找到该用户，则返回用户的 对象；否则返回 null</returns>
    public DirectoryEntry GetDirectoryEntryByAccount(string sAMAccountName, string password)
    {
        DirectoryEntry de = GetDirectoryEntryByAccount(sAMAccountName);
        if (de != null)
        {
            string commonName = de.Properties["cn"][0].ToString();
            if (GetDirectoryEntry(commonName, password) != null)
                return GetDirectoryEntry(commonName, password);
            else
                return null;
        }
        else
        {
            return null;
        }
    }

    /// <summary>
    /// 根据组名取得用户组的 对象
    /// </summary>
    /// <param name="groupName">组名</param>
    /// <returns></returns>
    public DirectoryEntry GetDirectoryEntryOfGroup(string groupName)
    {
        DirectoryEntry de = GetDirectoryObject();
        DirectorySearcher deSearch = new DirectorySearcher(de);
        deSearch.Filter = "(&(objectClass=group)(cn=" + groupName + "))";
        deSearch.SearchScope = SearchScope.Subtree;
        try
        {
            SearchResult result = deSearch.FindOne();
            de = new DirectoryEntry(result.Path);
            return de;
        }
        catch
        {
            return null;
        }
    }

    #endregion

    #region GetProperty



    /// <summary>
    /// 获得指定 指定属性名对应的值
    /// </summary>
    /// <param name="de">DirectoryEntry对象，如为用户则为用户的对象，部门则为部门的对象</param>
    /// <param name="propertyName">属性名称</param>
    /// <returns>属性值</returns>
    public string GetProperty(DirectoryEntry de, string propertyName)
    {
        if (de.Properties.Contains(propertyName))
        {
            return de.Properties[propertyName][0].ToString();
        }
        else
        {
            return string.Empty;
        }
    }

    ///
    /// 获得指定搜索结果 中指定属性名对应的值
    ///
    ///
    /// 属性名称
    /// 属性值
    public string GetProperty(SearchResult searchResult, string propertyName)
    {
        if (searchResult.Properties.Contains(propertyName))
        {
            return searchResult.Properties[propertyName][0].ToString();
        }
        else
        {
            return string.Empty;
        }
    }
    #endregion

    #region SetProperty
    /// <summary>
    /// 设置指定 的属性值
    /// </summary>
    /// <param name="de"></param>
    /// <param name="propertyName">属性名称</param>
    /// <param name="propertyValue">属性值</param>
    public void SetProperty(DirectoryEntry de, string propertyName, string propertyValue)
    {
        if (propertyValue != string.Empty || propertyValue != "" || propertyValue != null)
        {
            if (de.Properties.Contains(propertyName))
            {
                de.Properties[propertyName][0] = propertyValue;
            }
            else
            {
                de.Properties[propertyName].Add(propertyValue);
            }
        }
    }

    #endregion

    #region 用户操作

    /// <summary>
    /// 创建带邮箱的用户
    /// </summary>
    /// <param name="CommonName">通用名（displayName,系统中显示的中文名字）</param>
    /// <param name="Account">帐户名（如ycan）</param>
    /// <param name="organizeName">组织单元名（有色院/科技处/信息中心）</param>
    /// <param name="password">密码</param>
    /// <param name="CreateMail">是否创建邮箱</param>
    /// <returns>新建用户的Path 错误则为“”</returns>
    public string CreateADAccount(
        string CommonName,//CName
        string Account,//EName
        string organizeName,//
        string password,
        bool CreateMail
        )
    {
        //如果Acc存在则返回错误
        if (IsAccExists(Account))
            return "";
        DirectoryEntry entry = null;
        DirectoryEntry user = null;
        string samAccountName = Account;
        try
        {
            entry = new DirectoryEntry(GetOrganizeNamePath(organizeName), ADUser,
            ADPassword, AuthenticationTypes.Secure);

            user = entry.Children.Add("CN=" + CommonName, "user");
            user.Properties["userPrincipalName"].Value = samAccountName + sPrincpleNameTail;
            user.Properties["sAMAccountName"].Add(samAccountName);
            user.Properties["displayName"].Add(CommonName);

            user.CommitChanges();
            user.Invoke("SetPassword", new object[] { password });
            //This enables the new user.

            user.Properties["userAccountControl"].Value = //0x200; //ADS_UF_NORMAL_ACCOUNT
                 ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_NORMAL_ACCOUNT | ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD;
            user.CommitChanges();
            if (CreateMail)
            {
                user.Invoke("CreateMailbox", new object[] { homeMDB });
                user.CommitChanges();
            }
        }
        catch (Exception e)
        {
            try
            {
                user.DeleteTree();
            }
            catch
            {
                //return string.Empty;
            }
            throw e;
        }
        return user.Path;
    }


    /// <summary>
    /// 启用指定公共名称的用户
    /// </summary>
    /// <param name="commonName">用户公共名称</param>
    public void EnableUser(string commonName)
    {
        EnableUser(GetDirectoryEntry(commonName));
    }


    /// <summary>
    /// 启用指定帐户
    /// </summary>
    /// <param name="de"></param>
    public void EnableUser(DirectoryEntry de)
    {
        //impersonate.BeginImpersonate();
        de.Properties["userAccountControl"][0] =
            ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_NORMAL_ACCOUNT | ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD;
        de.CommitChanges();
        //impersonate.StopImpersonate();
        de.Close();
    }

    /// <summary>
    /// 禁用指定公共名称的用户
    /// </summary>
    /// <param name="commonName">用户公共名称</param>
    public void DisableUser(string commonName)
    {
        DisableUser(GetDirectoryEntry(commonName));
    }

    /// <summary>
    /// 禁用指定的帐户
    /// </summary>
    /// <param name="de"></param>
    public void DisableUser(DirectoryEntry de)
    {
        //impersonate.BeginImpersonate();
        de.Properties["userAccountControl"][0] =
            ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_NORMAL_ACCOUNT | ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD | ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_ACCOUNTDISABLE;
        de.CommitChanges();
        //impersonate.StopImpersonate();
        de.Close();
    }


    /// <summary>
    /// 修改用户密码
    /// </summary>
    /// <param name="commonName">用户公共名称</param>
    /// <param name="oldPassword">旧密码</param>
    /// <param name="newPassword">新密码</param>
    public void ChangeUserPassword(string commonName,
        string oldPassword, string newPassword)
    {
        // to-do: 需要解决密码策略问题
        DirectoryEntry oUser = GetDirectoryEntry(commonName);
        oUser.Invoke("ChangePassword", new Object[] { oldPassword, newPassword });
        oUser.Close();
    }

    /// <summary>
    /// 修改Acc密码
    /// </summary>
    /// <param name="sAMacc">帐户名称</param>
    /// <param name="oldPassword">旧密码</param>
    /// <param name="newPassword">新密码</param>
    /// <returns>是否成功</returns>
    public bool ChangeAccPassword(string sAMacc,
        string oldPassword, string newPassword)
    {
        try
        {
            if (IsAccExists(sAMacc))
            {
                // to-do: 需要解决密码策略问题
                DirectoryEntry oUser = GetDirectoryEntryByAccount(sAMacc);
                //oUser.Invoke("ChangePassword", new Object[] { oldPassword, newPassword });
                oUser.Invoke("SetPassword", new object[] { newPassword });
                oUser.CommitChanges();
                oUser.Close();
                return true;
            }
            else
                return false;
        }
        catch (Exception)
        {
            return false;
        }

    }



    /// <summary>
    /// 移动用户
    /// </summary>
    /// <param name="user_path">用户Path</param>
    /// <param name="target_path">目标path</param>
    /// <returns></returns>
    public string MoveUser(string user_path, string target_path)
    {
        DirectoryEntry u = new DirectoryEntry(user_path, ADUser, ADPassword);
        DirectoryEntry t = new DirectoryEntry(target_path, ADUser, ADPassword);
        u.MoveTo(t);
        return u.Path;
    }



    /// <summary>
    /// 重名用户
    /// </summary>
    /// <param name="sAcc"></param>
    /// <param name="newDisplayName"></param>
    /// <returns></returns>
    public bool RenameUser(string sAcc, string newDisplayName)
    {
        try
        {
            if (IsAccExists(sAcc))
            {
                DirectoryEntry userEntry = GetDirectoryEntryByAccount(sAcc);
                //userEntry.Properties["cn"][0] = newDisplayName;
                userEntry.Properties["displayName"][0] = newDisplayName;

                userEntry.Rename("CN=" + newDisplayName);
                userEntry.CommitChanges();
                userEntry.Dispose();
                return true;
            }
            else
                return false;
        }
        catch (Exception)
        {

            return false;
        }
    }

    /// <summary>
    /// 重命名Account
    /// </summary>
    /// <param name="oldAcc">原Acc</param>
    /// <param name="newAcc">新Acc</param>
    /// <returns>成功True，如果已经存在新、老Acc则返回false，错误也返回false</returns>
    public bool RenameAcc(string oldAcc, string newAcc)
    {
        try
        {
            if (IsAccExists(oldAcc))
            {
                //不允许同名ACC
                if (IsAccExists(newAcc))
                    return false;
                DirectoryEntry userEntry = GetDirectoryEntryByAccount(oldAcc);

                userEntry.Properties["sAMAccountName"][0] = newAcc;
                userEntry.CommitChanges();
                userEntry.Dispose();
                return true;
            }
            else
                return false;
        }
        catch (Exception)
        {

            return false;
        }

    }

    public void SetUserPassword(string userName, string password)
    {
        SetUserPassword(null, null, userName, password);
    }

    public void SetUserPassword(string adminName, string adminPassword, string userName, string password)
    {
        adminName = ADUser;
        adminPassword = ADPassword;
        DirectoryEntry userEntry = FindObject(adminName, adminPassword, "user", userName);
        userEntry.Invoke("SetPassword", new object[] { password });
        userEntry.CommitChanges();
    }


    /// <summary>
    /// 删除AD账户，使用当前上下文的安全信息，一般用于Windows程序
    /// </summary>
    /// <param name="userName">用户名称</param>
    /// <returns></returns>
    public bool DeleteADAccount(string Account)
    {
        //DeleteADAccount(null, null, userName);
        if (IsAccExists(Account))
        {
            string AccPath = GetAccPath(Account);
            DetTree(AccPath);
            return true;
        }
        else
            return false;
    }


    /// <summary>
    /// 删除AD账户，使用指定的用户名和密码来模拟，一般用于ASP.NET程序
    /// </summary>
    /// <param name="adminUser">AD管理员用户名，如默认，可以为null</param>
    /// <param name="adminPassword">AD管理员密码，如默认，可以为null</param>
    /// <param name="userName">用户名称</param>
    public bool DeleteADAccount(string adminUser, string adminPassword, string userName)
    {
        DirectoryEntry user = null;
        DirectoryEntry Container = null;
        try
        {
            adminUser = ADUser;
            adminPassword = ADPassword;
            user = FindObject(adminUser, adminPassword, "user", userName);
            Container = user.Parent;
            Container.Children.Remove(user);
            Container.CommitChanges();
            Container.Dispose();
            user.Dispose();
            return true;

        }
        catch (Exception)
        {
            Container.Dispose();
            user.Dispose();
            return false;
        }

    }

    public DirectoryEntry FindObject(string category, string name)
    {
        return FindObject(null, null, category, name);
    }

    public DirectoryEntry FindObject(string adminName,
        string adminPassword, string category, string name)
    {
        adminName = ADUser;
        adminPassword = ADPassword;
        DirectoryEntry de = null;
        //if (adminName == null || adminPassword == null)
        //{
        de = new DirectoryEntry(ADPath, adminName, adminPassword, AuthenticationTypes.Secure);
        //}
        //else
        //{
        //    de = new DirectoryEntry();
        //}
        ///organizationalUnit
        DirectorySearcher ds = new DirectorySearcher(de);
        string queryFilter = string.Format("(&(objectCategory=" +
            category + ")(sAMAccountName={0}))", name);
        ds.Filter = queryFilter;
        ds.Sort.PropertyName = "cn";

        DirectoryEntry userEntry = null;
        try
        {
            SearchResult sr = ds.FindOne();
            userEntry = sr.GetDirectoryEntry();
        }
        finally
        {
            if (de != null)
            {
                de.Dispose();
            }
            if (ds != null)
            {
                ds.Dispose();
            }
        }
        return userEntry;
    }

    #endregion

    #region 组织单元操作



    /// <summary>
    /// 重命名OU
    /// </summary>>
    /// <param name="oldOUName">原名</param>
    /// <param name="newOUName">新名</param>
    /// <returns>是否成功</returns>
    public bool RenameOU(string oldOUName, string newOUName)
    {

        try
        {
            if (CheckOU(oldOUName))
            {
                DirectoryEntry userEntry = new DirectoryEntry(GetOrganizeNamePath(oldOUName), ADUser, ADPassword);
                userEntry.Rename("OU=" + newOUName);
                userEntry.CommitChanges();
                userEntry.Dispose();
                if (CheckOU(newOUName))
                    return true;
                else
                    return false;
            }
            else
                return false;
        }
        catch (Exception)
        {
            return false;
            //throw;
        }
    }

    /// <summary>
    /// Get Users From OU
    /// </summary>>    
    /// <returns></returns>
    public DataTable GetUsersFromOU(string OUName)
    {
        try
        {
            if (CheckOU(OUName))
            {
                DirectoryEntry OUEntry = new DirectoryEntry(GetOrganizeNamePath(OUName), ADUser, ADPassword);
                //表名
                DataTable tbUsers = new DataTable("users");
                //用户列
                tbUsers.Columns.Add("UserID", System.Type.GetType("System.String"));
                tbUsers.Columns.Add("UserName", System.Type.GetType("System.String"));
                tbUsers.Columns.Add("UserAccount", System.Type.GetType("System.String"));
                DirectorySearcher src = new DirectorySearcher("(&(objectCategory=Person)(objectClass=user))");
                DirectoryEntry de = new DirectoryEntry(ADPath + "/OU=" + OUName + "," + LDAPDomain);
                src.SearchRoot = de;
                src.SearchScope = SearchScope.Subtree;
                string strUserAccount = null;

                foreach (SearchResult res in src.FindAll())
                {
                    System.Collections.IDictionaryEnumerator ien = res.Properties.GetEnumerator();
                    DataRow topRow = tbUsers.NewRow();
                    topRow["UserID"] = GetProperty(res, "Name");
                    topRow["UserName"] = GetProperty(res, "displayname");
                    //得到用户状态
                    int userAccountControl = Convert.ToInt32(GetProperty(res, "userAccountControl"));
                    //判断用户是否启用
                    if (IsAccountActive(userAccountControl))
                    {
                        topRow["UserAccount"] = "激活";
                    }
                    else
                    {
                        topRow["UserAccount"] = "禁用";
                    }
                    tbUsers.Rows.Add(topRow);
                }
                return tbUsers;
            }
            else
                return null;
        }
        catch (Exception)
        {
            return null;
            //throw;
        }
    }

    /// <summary>
    /// Get Users From File
    /// </summary>>    
    /// <returns></returns>
    public DataTable GetUsersFromFile(string FileName)
    {
        try
        {
            //表名
            DataTable tbUsers = new DataTable("users");
            //用户列
            tbUsers.Columns.Add("UserID", System.Type.GetType("System.String"));
            tbUsers.Columns.Add("UserName", System.Type.GetType("System.String"));
            tbUsers.Columns.Add("UserAccount", System.Type.GetType("System.String"));
            DirectorySearcher src = new DirectorySearcher("(&(objectCategory=Person)(objectClass=user))");
            DirectoryEntry de = new DirectoryEntry(ADPath + "/CN=" + FileName + "," + LDAPDomain);
            src.SearchRoot = de;
            src.SearchScope = SearchScope.Subtree;
            string strUserAccount = null;

            foreach (SearchResult res in src.FindAll())
            {
                System.Collections.IDictionaryEnumerator ien = res.Properties.GetEnumerator();
                DataRow topRow = tbUsers.NewRow();
                topRow["UserID"] = GetProperty(res, "Name");
                topRow["UserName"] = GetProperty(res, "displayname");
                //得到用户状态
                int userAccountControl = Convert.ToInt32(GetProperty(res, "userAccountControl"));
                //判断用户是否启用
                if (IsAccountActive(userAccountControl))
                {
                    topRow["UserAccount"] = "激活";
                }
                else
                {
                    topRow["UserAccount"] = "禁用";
                }
                tbUsers.Rows.Add(topRow);
            }
            return tbUsers;
        }
        catch (Exception)
        {
            return null;
            //throw;
        }
    }

    /// <summary>
    /// 检查组织单位（OU）是否存在
    /// </summary>
    /// <param name="sOU">组织单位名称 </param>
    /// <returns>成功返回True,否则返回False</returns>
    public bool CheckOU(string sOU)
    {
        DirectoryEntry objOU = null;
        try
        {
            objOU = new DirectoryEntry(GetOrganizeNamePath(sOU), ADUser, ADPassword);
            string OUName = objOU.Name;
            //if (OUName == sOU)
            objOU.Close();
            objOU = null;
            return true;
        }
        catch
        {
            objOU.Close();
            objOU = null;
            return false;
        }
    }

    /// <summary>
    /// 创建OU，需要指定连接到AD的授权信息
    /// </summary>
    /// <param name="adminName"></param>
    /// <param name="adminPassword"></param>
    /// <param name="name"></param>
    /// <param name="parentOrganizeUnit"></param>
    public DirectoryEntry CreateOrganizeUnit(string adminName,
        string adminPassword, string name, string parentOrganizeUnit)
    {
        adminName = ADUser;
        adminPassword = ADPassword;
        DirectoryEntry parentEntry = null;
        if (adminName == null || adminPassword == null)
        {
            parentEntry = new DirectoryEntry(GetOrganizeNamePath(parentOrganizeUnit));
        }
        else
        {
            if (parentOrganizeUnit != "")
            {
                parentEntry = new DirectoryEntry(GetOrganizeNamePath(parentOrganizeUnit),
                   adminName, adminPassword,
                   AuthenticationTypes.Secure);
            }
            else
            {
                parentEntry = new DirectoryEntry(GetOrganizeNamePath(parentOrganizeUnit),
                     adminName, adminPassword,
                     AuthenticationTypes.Secure);
            }
        }
        DirectoryEntry organizeEntry = parentEntry.Children.Add("OU=" +
            name, "organizationalUnit");
        organizeEntry.CommitChanges();
        return organizeEntry;
    }

    /// <summary>
    /// 创建OU，不需要指定连接到AD的授权信息，用于Windows程序
    /// </summary>
    /// <param name="name">OU name</param>
    /// <param name="parentOrganizeUnit">父OU路径如a/b/c</param>
    public DirectoryEntry CreateOrganizeUnit(string name, string parentOrganizeUnit)
    {
        return CreateOrganizeUnit(null, null, name, parentOrganizeUnit);
    }

    /// <summary>
    /// 将用户加入到用户组中
    /// </summary>
    /// <param name="userName">用户名</param>
    /// <param name="organizeName">组织名</param>
    /// <param name="groupName">组名</param>
    /// <exception cref="InvalidObjectException">用户名或用户组不存在</exception>
    public void AddUserToGroup(string userName, string groupName)
    {
        AddUserToGroup(null, null, userName, groupName);
    }

    /// <summary>
    /// 将用户加入到用户组中
    /// </summary>
    /// <param name="adminName"></param>
    /// <param name="adminPassword"></param>
    /// <param name="userName">用户名</param>
    /// <param name="groupName">组名</param>
    /// <exception cref="InvalidObjectException">用户名或用户组不存在</exception>
    public void AddUserToGroup(string adminName, string adminPassword, string userName, string groupName)
    {
        adminName = ADUser;
        adminPassword = ADPassword;
        DirectoryEntry rootUser = null;
        if (adminName == null || adminPassword == null)
        {
            rootUser = new DirectoryEntry(GetUserPath(), adminName, adminPassword, AuthenticationTypes.Secure);
        }
        else
        {
            rootUser = new DirectoryEntry(GetUserPath());
        }

        DirectoryEntry group = null;
        DirectoryEntry user = null;

        try
        {
            group = rootUser.Children.Find("CN=" + groupName);
        }
        catch (Exception)
        {
            throw new Exception("在域中不存在组“" + groupName + "”");
        }

        try
        {
            user = FindObject(adminName, adminPassword, "user", userName);
        }
        catch (Exception)
        {
            throw new Exception("在域中不存在用户“" + userName + "”");
        }

        //加入用户到用户组中
        group.Properties["member"].Add(user.Properties["distinguishedName"].Value);
        group.CommitChanges();
    }


    /// <summary>
    /// 彻底删除OU/也可以通过参数控制删除空OU,即安全删除
    /// </summary>
    /// <param name="OUName">OU名,如a/b/c,必须写绝对OU名</param>
    /// <param name="boolComplete">true为彻底删除,false为安全删除</param>
    /// <returns>成功与否</returns>
    public bool DeleteOU(string OUName, bool boolComplete)
    {
        try
        {
            if (!boolComplete)
                return false;
            if (CheckOU(OUName))
            {
                string OUpath = GetOrganizeNamePath(OUName);
                if (OUpath == "")
                    return false;
                else
                {
                    DetTree(OUpath);
                    return true;
                }
            }
            else
                return true;
        }
        catch (Exception)
        {
            throw;
            //return false;
        }
    }

    /// <summary>
    /// 删除OU（仅仅支持纯部门删除，OU中不能有其他用户、OU等信息的子节点）
    /// </summary>
    /// <param name="OUName">OU名,如a/b/c,必须写绝对OU名</param>
    /// <returns>"成功"  "不存在"  "非空"</returns>
    public string DeleteOU(string OUName)
    {
        try
        {
            if (CheckOU(OUName))
            {
                DirectoryEntry objOU = new DirectoryEntry(GetOrganizeNamePath(OUName));
                DirectoryEntry parOU = objOU.Parent;
                parOU.Children.Remove(objOU);
                parOU.CommitChanges();
                return "成功";
            }
            else
                return "不存在";
        }
        catch (Exception)
        {
            return "非空";
        }
    }


    #endregion

    #region 登录相关

    /// <summary>
    /// 判断用户与密码是否足够以满足身份验证进而登录
    /// </summary>
    /// <param name="commonName">用户公共名称</param>
    /// <param name="password">密码</param>
    /// <returns>如能可正常登录，则返回 true；否则返回 false</returns>
    public LoginResult Login(string commonName, string password)
    {
        DirectoryEntry de = GetDirectoryEntry(commonName);

        if (de != null)
        {
            // 必须在判断用户密码正确前，对帐号激活属性进行判断；否则将出现异常。
            int userAccountControl =
                Convert.ToInt32(de.Properties["userAccountControl"][0]);
            de.Close();
            if (!IsAccountActive(userAccountControl))

                return LoginResult.LOGIN_USER_ACCOUNT_INACTIVE;
            if (GetDirectoryEntry(commonName, password) != null)
                return LoginResult.LOGIN_USER_OK;
            else
                return LoginResult.LOGIN_USER_PASSWORD_INCORRECT;
        }
        else
        {
            return LoginResult.LOGIN_USER_DOESNT_EXIST;
        }
    }


    /// <summary>
    /// 判断用户帐号与密码是否足够以满足身份验证进而登录
    /// </summary>
    /// <param name="sAMAccountName">用户帐号</param>
    /// <param name="password">密码</param>
    /// <returns>如能可正常登录，则返回 true；否则返回 false</returns>
    public LoginResult LoginByAccount(string sAMAccountName, string password)
    {
        DirectoryEntry de = GetDirectoryEntryByAccount(sAMAccountName);
        if (de != null)
        {
            // 必须在判断用户密码正确前，对帐号激活属性进行判断；否则将出现异常。
            int userAccountControl =
                Convert.ToInt32(de.Properties["userAccountControl"][0]);
            de.Close();
            if (!IsAccountActive(userAccountControl))
                return LoginResult.LOGIN_USER_ACCOUNT_INACTIVE;
            if (GetDirectoryEntryByAccount(sAMAccountName, password) != null)
                return LoginResult.LOGIN_USER_OK;
            else
                return LoginResult.LOGIN_USER_PASSWORD_INCORRECT;
        }
        else
        {
            return LoginResult.LOGIN_USER_DOESNT_EXIST;
        }
    }

    /// <summary>
    /// 判断用户帐号是否激活
    /// </summary>
    /// <param name="userAccountControl">用户帐号属性控制器</param>
    /// <returns>如果用户帐号已经激活，返回 true；否则返回 false</returns>
    public bool IsAccountActive(int userAccountControl)
    {
        int userAccountControl_Disabled =
            Convert.ToInt32(ADS_USER_FLAG_ENUM.ADS_UF_ACCOUNTDISABLE);
        int flagExists = userAccountControl & userAccountControl_Disabled;
        if (flagExists > 0)
            return false;
        else
            return true;
    }

    /// <summary>
    ///  判断用户是否存在
    /// </summary>
    /// <param name="commonName">公用名</param>
    /// <returns></returns>
    public bool IsUserExists(string commonName)
    {
        DirectoryEntry de = GetDirectoryObject();
        DirectorySearcher deSearch = new DirectorySearcher(de);
        deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(cn=" + commonName + "))";       // LDAP 查询串
        SearchResultCollection results = deSearch.FindAll();
        if (results.Count == 0)
            return false;
        else
            return true;
    }
    /// <summary>
    ///  判断帐户是否存在
    /// </summary>
    /// <param name="commonName">Account用户名</param>
    /// <returns>是否存在</returns>
    public bool IsAccExists(string sAMAccountName)
    {
        DirectoryEntry de = GetDirectoryObject();
        DirectorySearcher deSearch = new DirectorySearcher(de);
        deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(sAMAccountName=" +
            sAMAccountName + "))";       // LDAP 查询串
        SearchResultCollection results = deSearch.FindAll();
        if (results.Count == 0)
            return false;
        else
            return true;
    }

    #endregion

    #region 与AD的DN解析有关工具函数

    /// <summary>
    /// 删除对象
    /// </summary>
    /// <param name="path">对象路径</param>
    public void DetTree(string path)
    {
        try
        {
            DirectoryEntry ent = new DirectoryEntry(path, ADUser, ADPassword);
            ent.DeleteTree();

        }
        catch (Exception e)
        {
            throw e;
        }
    }


    /// <summary>
    /// 获取所有用户所在的安全组
    /// </summary>
    /// <returns></returns>
    private string GetUserPath()
    {
        return GetUserPath(null);
    }

    /// <summary>
    /// 获取所有没有在AD组织中的用户DN名称
    /// </summary>
    /// <param name="userName"></param>
    /// <returns></returns>
    private string GetUserPath(string userName)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(ADPath);
        if (userName != null && userName.Length > 0)
        {
            sb.Append("CN=").Append(userName).Append(",");
        }
        sb.Append("CN=Users,").Append(GetDomainDN());
        return sb.ToString();
    }

    /// <summary>
    /// 根据用户所在的组织结构来构造用户在AD中的DN路径
    /// </summary>
    /// <param name="userName">用户名称</param>
    /// <param name="organzieName">组织结构</param>
    /// <returns></returns>
    public string GetUserPath(string userName, string organzieName)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(ADPath);
        sb.Append("CN=").Append(userName).Append(",").Append(SplitOrganizeNameToDN(organzieName));
        return sb.ToString();
    }
    /// <summary>
    /// 获得帐户Acc的Path
    /// </summary>
    /// <param name="sAcc">Acc</param>
    /// <returns>错误就是empty</returns>
    public string GetAccPath(string sAcc)
    {
        DirectoryEntry de = GetDirectoryObject();
        DirectorySearcher deSearch = new DirectorySearcher(de);
        deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(sAMAccountName=" + sAcc + "))";
        deSearch.SearchScope = SearchScope.Subtree;
        try
        {
            SearchResult result = deSearch.FindOne();
            string Apath = result.Path;
            result = null;
            deSearch.Dispose();
            de.Dispose();
            return Apath;
        }
        catch (Exception)
        {
            deSearch.Dispose();
            de.Dispose();
            return string.Empty;
        }
    }

    /// <summary>
    /// 获取域的后缀DN名,如域为cinf.com,则返回"DC=cinf,DC=Com"
    /// </summary>
    /// <returns></returns>
    public string GetDomainDN()
    {
        return LDAPDomain;
    }
    /// <summary>
    /// 获得OU的Path
    /// </summary>
    /// <param name="organizeUnit">OU名</param>
    /// <returns></returns>
    public string GetOrganizeNamePath(string organizeUnit)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(ADPath);//LDAP_IDENTITY
        sb.Append("/");
        return sb.Append(SplitOrganizeNameToDN(organizeUnit)).ToString();
    }

    /// <summary>
    /// 分离组织名称为标准AD的DN名称,各个组织级别以"/"或"\"分开。如"总部/物业公司/小区"，并且当前域为
    /// ExchangeTest.Com，则返回的AD的DN表示名为"OU=小区,OU=物业公司,OU=总
    /// 部,DC=ExchangeTest,DC=Com"。
    /// </summary>
    /// <param name="organizeName">组织名称</param>
    /// <returns>返回一个级别</returns>
    public string SplitOrganizeNameToDN(string organizeName)
    {
        StringBuilder sb = new StringBuilder();

        if (organizeName != null && organizeName.Length > 0)
        {
            string[] allOu = organizeName.Split(new char[] { '/', '\\' });
            for (int i = allOu.Length - 1; i >= 0; i--)
            {
                string ou = allOu[i];
                if (sb.Length > 0)
                {
                    sb.Append(",");
                }
                sb.Append("OU=").Append(ou);
            }
        }
        //如果传入了组织名称，则添加,
        if (sb.Length > 0)
        {
            sb.Append(",");
        }
        sb.Append(GetDomainDN());
        return sb.ToString();
    }
    #endregion
}
